package com.gitee.feizns.convert;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * @author feizns
 * @since 2019/5/19 0019
 */
public abstract class DateConvertUtils {

    /**
     * 毫秒转日期
     */
    private static final Map<Class<? extends Date>, Function<Long, ? extends Date>>
            MILLISECOND_CONVERSION = new HashMap<>();

    /**
     * 日期格式
     */
    private static final List<String> PATTERNS = new ArrayList<String>();

    static {
        //毫秒到日期
        {
            MILLISECOND_CONVERSION.put(java.util.Date.class, java.util.Date::new);
            MILLISECOND_CONVERSION.put(java.sql.Date.class, java.sql.Date::new);
            MILLISECOND_CONVERSION.put(java.sql.Timestamp.class, java.sql.Timestamp::new);
            MILLISECOND_CONVERSION.put(java.sql.Time.class, java.sql.Time::new);
        }

        //常用格式
        {
            PATTERNS.add("yyyy-MM-dd HH:mm:ss");
            PATTERNS.add("yyyy/MM/dd HH:mm:ss");
            PATTERNS.add("yyyy-MM-dd'T'HH:mm:ss");
            PATTERNS.add("yyyy-MM-dd");
            PATTERNS.add("yyyy/MM/dd");
            PATTERNS.add("HH:mm:ss");
        }
    }

    /**
     * 转毫秒
     * @param date
     * @return
     */
    public static final long toMillisecond(java.util.Date date) {
        return date.getTime();
    }

    /**
     * 字符日期转毫秒
     * @param date
     * @return
     */
    public static final Long toMillisecond(String date, String pattern) {
        try {
            return new SimpleDateFormat(pattern).parse(date).getTime();
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 常用格式转换
     * @param date
     * @return
     */
    public static final Long toMillisecond(String date) {
        for (String pattern : PATTERNS) {
            Long millisecond = toMillisecond(date, pattern);
            if ( millisecond != null )
                return millisecond;
        }
        return null;
    }

    /**
     * 毫秒转日期
     * @param milliSecond
     * @param targetType
     * @param <T>
     * @return
     */
    public static final <T extends java.util.Date> T to(long milliSecond, Class<T> targetType) {
        Function<Long, ? extends Date> longFun = MILLISECOND_CONVERSION.get(targetType);
        return longFun != null ? (T) longFun.apply(milliSecond) : null;
    }

    /**
     * 毫秒转日期
     * @param original
     * @param targetType
     * @param <T>
     * @return
     */
    public static final <T extends java.util.Date> T to(Object original, Class<?> targetType) {
        Long millisecond = null;

        if ( original instanceof Number ) {
            millisecond = ((Number) original).longValue();
        }

        if ( millisecond == null ) {
            millisecond = toMillisecond(original.toString());
        }

        Function<Long, ? extends Date> longFun = MILLISECOND_CONVERSION.get(targetType);
        return (longFun != null && millisecond != null) ? (T) longFun.apply(millisecond) : null;
    }

    /**
     * 注册格式
     * @param pattern
     */
    public static final void registryPattern(String pattern) {
        PATTERNS.add(pattern);
    }

}
